home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 6
/
Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso
/
027a
/
sg202.zip
/
SCROLGET.PRG
< prev
Wrap
Text File
|
1991-08-18
|
36KB
|
978 lines
/*
Version 2.02 of 18.08.91, 22:20 MEZ (Central European Standard Time)
This is a greatly improved version of a program wich has been spread
as scrolget.zip (.arj etc) thru BBS
This new version isn't backward compatible. But you cann now incorporate
it directly within your programs. Just use the Virtualget Command
to define your gets and the scrolread() function to read them.
While using scrollread, all parameters except the first one (containing
the vGetlist) are optional.
Scrolread() now cann replace 95 % of the cases you usualy would
use readmodal() or the read command
Revision History :
15.08.91
- corrected some small typos within the documentation text
- added some more documentation here and there (i.e. see Caveats)
- added enviroment saving and restoring within scrollread()
18.08.91 - Big improvments :
- The color-Bug of the previous version has been sorted out
- The Custom readerblock of the getobject is now processed,
if there is any
- Now PgDn and PgDn work as expected : They scroll a Page forward
respective backwards
Ctrl-Pgup will now get you to the first page, Ctrl-PgDn to the last one..
- Calculating new Getrows now allways depends on the Cargo-Value and not on
the actual Rows in Get:Row instance variable. This was changed, as
it seems that the Get:Row-Instance variable cann't have any negative
value (it's appearently converted to 65535 - Value)
- The scrolling-Logic should now also manage very strange situations,
where you have very wild get ordering, one on the first page, the next
one on the 4th page, the next one on the second etc
- changed left() to padr() in Showbg to successfully clear the line
when a line of the background array is shorter then the screen width
- added table of contents at the end of the documentation part
- documented how to use Get-Background and why I implemented it this way
- changed Prevalidate() and Postvalidate() functions to static, so that
they don't interfere with the functions of the same name within
clipper's getsys.prg
18.08.91, 21:00
- changed calling conventions of scrolget to four boxcoordinates rather
than boxheigth and boxwidth (I'm more accustomed to this mode from
the other clipper functions).
- new Parameter "mode" : if you pass an "V" like View, it will display the
box with the getfields only and then exit immidiatly
- The useless calls to the InfoBox-Functions have been thrown out..
- more documentation on the new features
This program shows how to do scrolling gets in Clipper 5.01
It will also scroll the Background with it .....
So you are able to edit forms of some pages within a 10 Lines Box..
This version only implements vertical scrolling
The getsystem is based on a template I made out of
"WEIRDGETS.PRG/Funcs.ch" a beautiful demo of the Clipper 5 Getsystem
done by The People from Nantucket Canada..
I understand they placed it into Public Domain...
It's also based on a readsystem I wrote for Clipper S'87 to implement
when clauses, scrolling gets and other things in that Clipper Version...
The GetPreValidate and GetPostValidate functions are shortcuts of the
same functions found in Getsys.prg provided by Nantucket.
I only changed it in a way that it will do scrolling gets and I throwed
out all non scrolling related features...
The Code is extremly documented, there is much more documentation than code.
I hope this will make it easy for you to implement it within your own
programs.
The original Version, wich just scrolled gets (The first Program
available via BBS to do so, as far as I know), is the result of
some two days of typing and was done in July 1991 by Kai Froeb
(Kai is pronounced like ki (i in like))
I'm a 27 years old Clipper Programmer,
living in Schumanstr.8, W-8500 Nürnberg 80, Germany
Tel : 0049-911-316838
FidoNet : 2:246/16.6
Internet : k.froeb@msn.rmi.de
I'd loved to be contacted by other Clipper Programmers....
Especialy I'd like to see any enhancements you made out of this...
You may freely use and modify the source. If you're developing libraries,
you can also incorporate a version of this program in your library.
I'd like seeing you giving me some credits for this,
but there's no need if you don't want to..
Caveats :
- Demo will only look nice on ega/Vga screens due to blinking colors..
- My Valid and Whenclause processing doesn't update the update variable,
calls to update()-Function will therefore be useless. Also, the
IMHO idiotic Scoreboard()-Function has been thrown out...
- No range Clause provided
- scrollread() uses F10 as Save&Exit Key, it saves and restores the original
F10 setting, but within scrolget, F10 has this special effect.
comment it out if you don't like that or feel free to change it to
another key
- scrollread() uses the Cargo-Instancevariable of the Getobjects
for the actual implementation of the virtual Getrows and -columns
IF you're using The Cargo-Variable allready, search with your texteditor
for cargo[CARGO_ROW] and cargo[CARGO_COL] and replace the Index
with other (probably higher) numbers..
- Pay attention that scrollread uses rows and columns,
calculated RELATIVE to the boxborder, in a way that they start
from the begining of the box(window).
I.E., if you have a box placed at @ 4,5 and therein a get
wich you define to be located at @ 1,1, this get field will
appear at absolute @ 4+1,5+1 = @ 5,6
- TimeToExit() (Last Function in this file) asks the user if sHe wants
to save/abort. Non-English Programs should have a modified version
of this Function, as it's in english (fortunatly, it's the only
language dependant part herein). You also may wish to use your
own boxing/Questioning Routines with that function..
- When defining a Background, this Background should not exceed
the highest Getrow by a Boxheigth
(i.e. : if your boxheigth is 10 and your highest virtual getrow is 30,
your Background mustn't have more then 39 lines),
otherwise you might get problems with the PgUp/PgDn key combinations
- When Using the virtualget Command, be carrefull when using it with
Arrays. If you have a for next loop like this :
for nKounter := 1 to 10
@ nKounter , nOffset virtualget aValue[nKounter]
next
You run into problems, as the Preprocessor will turn aValue[nKounter]
into a Codeblock with a reference to nKounter. So, when you try to
scrollread it, eval will 10 times find aValue[11] (11 is the assumed
value after leaving the for next loop)
Better define gets for Arrays directly e.g. :
#define lstr(x) ltrim(str(x))
for nKounter = 1 to 10
aadd(vGetlist,GetNew( nKounter, nOffset,;
&("{|NewValue|iif(NewValue=NIL,aValues["+lstr(nKounter)+"],";
aValues["+lstr(nKounter)+"]:=NewValue)}"),:
aValues["+lstr(nKounter)+"]")
next
Known Bugs :
- None :-))
Compile with clipper scrolget /A /B /N /M /W
(minimum is /N)
Link with rtlink fi scrolget or blinker fi scrolget
The program consists of the following UDFs :
* DemoScroll - Demo for Scrolling Gets
* scrollread - The Scrolling-Get engine (sort of replace for Readmodal)
* FirstGetinBox - Find the Number of the Get in the upper left corner
* MaxGetrow - Find the Number of the Get with the highest Virtual Line Number
* ScrollNext - Calculate new rows when Scrolling to the next get
* ShowGetBG - Display the Getbackground (Titles etc) wich fits in the box
* NewGetRows - Reset the row values in the Getobject to new values
* NewGetCols - Reset the column values in the Getobject to new values
* ShowGets - Display the Gets wich fit in the box
* GetFocus - activate / deactivate a Get
* GetPreValidate - check When Clause of Get
* GetPostValidate - check Valid clause of Get
* Shad - Draw a shadowed Box
* TimeToExit - Popup Box to ask the user if sHe realy wants to exit
*/
// Symbolic Names for Inkey-values
#include "inkey.ch"
// funcs.ch came from Nantucket Canada. I just took out the parts
// needed for this demo..
#include "funcs.ch"
// first element in Cargo Array of getelements indicates virtual row
#define CARGO_ROW 1
// second element in Cargo Array of getelements indicates virtual column
#define CARGO_COL 2
// With the default Get command, the gets are displayed the same time
// they are defined. This is not what I want here. I just want to define the
// gets, but display them later. That's exactly what my alternative
// implementation of the Get command, Virtualget, does (it only defines them)
// You may use this command to define your own getobjects as well,
// it is a stand alone command. Only take attention, that this
// Command uses the variable vGetlist rather then Getlist,
// What you cann change of course, if you like...
// You also may change it's name Virtualget to Vget, what's less
// work to write in full length...
// Using xcommand means, that you can't abriviate the command by 4 letters
// I'm using xcommands for my preprocessor Commands, as I found it rather
// difficult to watch for not using possible abriviatons of my so defined
// commands by chance..
#xcommand @ <row>, <col> VIRTUALGET <var> ;
[PICTURE <pic>] ;
[VALID <valid>] ;
[WHEN <when>] ;
[COLOR <color>] ;
[SEND <msg>] ;
;
=> iif(vGetlist=NIL,vGetlist:={},NIL) ;
;AAdd( ;
vGetlist, ;
GetNew( <row>,<col>, ;
{|NewValue|iif(NewValue=NIL,<var>,<var>:=NewValue)}, ;
<(var)>, <(pic)>, <(color)>) ;
) ;
[; ATail(vGetlist):PostBlock := <{valid}>] ;
[; ATail(vGetlist):PreBlock := <{when}>] ;
[; ATail(vGetlist):<msg>]
function DemoScroll()
/*****************************************
0 1════════╗ <--- Background
1 2 ║
2 1──3────────╫────┐ Boxtop =2
3 2 4BGTOP=4 ║ │<------- Box (Window)
4 3 5 ║ │ Boxh =5
5 4 6BGbot=6 ║ │
6 5──7────────╫────┘ Boxbot =6
7 8════════╝ BGh =8
******************************************/
local Boxtop := 2 // Boxtop
local Boxh := 11 // Boxheigth
local Boxleft:= 5 // Boxleft
local Boxw := 66 // Boxwidth
local GetBG := {} // Get-Background
local BGtop := 1 // first Line of Get-Background displayed within Box
local BGh // Get-Background consists of how many lines ?
local BGColor := "BG/B" // Color of Get-Background
// also used as color of the Getbox itself
local vGetlist := {} // The Getlist..
local nKounter // for a for-Next-Loop
local cDefcol // for Panel() (see funs.ch)
local cGetNo_1 , cGetNo_2 , cGetNo_3 , cGetNo_4 ,;
cGetNo_5 , cGetNo_6 , cGetNo_7 , cGetNo_8 , cGetNo_9,;
cGetNo_10, cGetNo_11 , cGetNo_12 , cGetNo_13 , cGetNo_14 ,;
cGetNo_15 , cGetNo_16 , cGetNo_17 , cGetNo_18 , cGetNo_19
// Here I'm defining some sample Getvalues, so that you can easyly
// figure out on wich get you are..
// Initializes them with 60 spaces
cGetNo_1 := "1"+space(59)
cGetNo_2 := "2"+space(59)
cGetNo_3 := "3"+space(59)
cGetNo_4 := "4"+space(59)
cGetNo_5 := "5"+space(59)
cGetNo_6 := "6"+space(59)
cGetNo_7 := "7"+space(59)
cGetNo_8 := "8"+space(59)
cGetNo_9 := "9"+space(59)
cGetNo_10 := "10"+space(58)
cGetNo_11 := "11"+space(58)
cGetNo_12 := "12"+space(58)
cGetNo_13 := "13"+space(58)
cGetNo_14 := "14"+space(58)
cGetNo_15 := "15"+space(58)
cGetNo_16 := "16"+space(58)
cGetNo_17 := "17"+space(58)
cGetNo_18 := "18"+space(58)
cGetNo_19 := "19"+space(58)
// The colors the Nantucket People choosed look neat,
// but make only sense on an ega or vga monitor,
// where you cann hilite colors instead of blinking attribute..
SETBLINK( .F. )
// Just some screen setup.. (see funs.ch)
Panel(.t.)
// Define your Gets with scrollread for your convenience..
// If you want to test the clauses, just take away the //s below
// or try your own ones..
@ 1,3 virtualget cGetNo_1 color 'w+/rb, w+/r' // valid ! empty(cGetNo_1)
@ 3,3 virtualget cGetNo_2 color 'w+/rb, w+/b'
@ 5,3 virtualget cGetNo_3 color 'w+/rb, w+/gr' // when ! "e" $ cGetNo_3
@ 7,3 virtualget cGetNo_4 color 'w+/rb, w+/bg'
@ 9,3 virtualget cGetNo_5 color 'w+/rb, w+/N' // picture "@!"
@ 11,3 virtualget cGetNo_6 color 'w+/rb, w+/b+'
@ 13,3 virtualget cGetNo_7 color 'w+/rb, w+/g'
@ 15,3 virtualget cGetNo_8 color 'w+/rb, w+/B*'
@ 17,3 virtualget cGetNo_9 color 'w+/rb, w+/r+'
@ 19,3 virtualget cGetNo_10 color 'w+/rb, w+/b+'
@ 21,3 virtualget cGetNo_11 color 'w+/rb, w+/r' // valid ! empty(cGetNo_1)
@ 23,3 virtualget cGetNo_12 color 'w+/rb, w+/b'
@ 25,3 virtualget cGetNo_13 color 'w+/rb, w+/gr' // when ! "e" $ cGetNo_3
@ 27,3 virtualget cGetNo_14 color 'w+/rb, w+/bg'
@ 29,3 virtualget cGetNo_15 color 'w+/rb, w+/N' // picture "@!"
@ 31,3 virtualget cGetNo_16 color 'w+/rb, w+/b+'
@ 33,3 virtualget cGetNo_17 color 'w+/rb, w+/g'
@ 35,3 virtualget cGetNo_18 color 'w+/rb, w+/B*'
@ 37,3 virtualget cGetNo_19 color 'w+/rb, w+/r+'
// This version assumes you have a Background within the getbox, e.g.
// for Get-Titles and other things. This Background is implemented in form
// of an Array, where every line of the background corresponds to one
// element in the array. So you'll have to declare this array. It should
// have minimum as much lines as the higest value for the getrows
// e.g. if you have a
// @ 250, 3 virtualget cTest
// in your program, the background has to be an array of minimum
// 250 Elements. They all need to be of type Characters
// (fill with "", if you don't use them)
//
// Why implement the Background like this ?
// - Better a Background then Fieldtitles only, so that one has
// more options (i.e. this way, you can include boxes etc )
// - Better realize it as array then as a string, as :
// a) it's much faster to grab the lines with GetBg[LineNumber] then
// grabbing it thru memoline, what is very slow (and a string with
// fixed linelength on the other hand takes much too much memory).
// b) displaying with aeval-Function (see ShowBg()) is much faster
// then a for next loop
// c) When you use scrollread() in a generic routine, wich automaticaly
// calculates the Getscreens, so that one get is placed beyond the
// other, row by row and you have an array of fieldtitles available,
// you could pass this array will do very well as background.
// Also, if you don't have an array of fieldtitles, an Array with
// fieldnames will do the job, too.
// Fill Dummy Background, every Line with another Letter...
for nKounter :=1 to 37
aadd(GetBG,replicate(chr(64+nKounter),80))
next
// Background will now look like that :
// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
// etc
// The Getarray defined with virtualgets is named vGetlist
if scrollread(vGetlist,GetBg,Boxtop,Boxleft,Boxh,Boxw,BGcolor)
// User choosed "Save Changes",
// so place your Replace commands here
// For the new values, refer to vGetlist, wich, as beeing an array,
// has been passed to scrollread() via Reference and so now
// reflects all changes made therein
else
// User aborted Get
// Place any command to handle this situation (Warnings or whatever)
// here
endif
return nil
*-----------------------------------------------------------------
FUNCTION scrollread(aGet,GetBg,Boxtop,Boxleft,Boxbot,Boxright,BGcolor,nGet,bDrawBox,mode)
local cThisGet, lSkiped := .f.
LOCAL nKey := 0, nLastGet, BGh,BGTop,nKounter, Boxh, Boxw
LOCAL lInsert := .T.
local cO_color,nO_cursor,bO_f10key
// all Parameters except aGet are optional, so check them
if valtype(mode) <>"C"
mode = "E"
endif
if valtype(Boxtop) <>"N" .and. valtype(Boxleft) <>"N" .and. valtype(bDrawbox) <>"B"
// No coordinates passed, assume they wish to have it very much
// compatible to the usual get/read command - so we provide no box
bDrawBox:={||.t.} // assume no box
endif
if valtype(Boxtop) <>"N"
Boxtop =0
endif
if valtype(Boxleft) <>"N"
Boxleft =0
endif
if valtype(Boxbot) <>"N"
Boxbot = Maxrow()
endif
if valtype(Boxright) <>"N"
Boxw = Maxcol()
endif
if valtype(BGColor) <>"C"
BGColor = setcolor()
endif
if valtype(nGet) <>"N"
nGet := 1
endif
if valtype(GetBG) <> "A"
GetBG := array(aGet[MaxGetRow(aGet)]:Row)
afill(GetBG,"")
endif
Boxh = Boxbot - Boxtop+1
Boxw = Boxright - Boxleft+1
BGh := len(GetBg) // Tell system how many backgroundlines there are
BGTOP := max(aGet[nGet]:Row-Boxh+3,1)
if valtype(bDrawBox) <> "B"
// Draws the GET Frame.. (see UDF below)
bDrawBox:={||Shad( Boxtop, Boxleft, Boxbot, Boxright , .T., BGcolor )}
endif
// Save the enviroment :
cO_color := setcolor()
nO_cursor := setcursor()
bO_f10Key := setkey(K_F10,NIL) // free F10-Key, so that we cann use it
// nLastget is set to a dummy value (must be same as nGet)
nLastGet := nGet
// Save the original Boxrows and Cols..
aeval(aGet,{|oGet|oGet:Cargo := {oGet:Row,oGet:Col}})
// Now change the Get-Columns to fit into the box..
// Newgetcols() is a UDF below..
NewGetCols(aGet,Boxleft)
// Same with Get-Rows.. (Newgetrows() is a UDF below..)
NewGetRows(aGet,Boxtop,Bgtop)
// Draws the GET Frame.. (see funcs.ch)
eval(bDrawBox)
// Draw the Background of the Gets.. (Titles etc)
ShowGetBG(GetBG,Boxtop,Boxleft,Boxw,BGTOP,Boxh-2,BGcolor)
// Display those gets which fit into the box :
ShowGets(aGet,nGet,Boxtop,Boxh)
// Positions the cursor to the first position in the first GET
DEVPOS( aGet[nGet]:ROW, aGet[nGet]:COL )
// Process Keystrokes in a Loop until the user wants to exit
// Don't enter this Loop, if we're in display-only mode
DO while mode != "V" .and. nKey != K_F10
lSkiped := .f. // Set within When-Clause processing. Reset to .f. first
do case
* If the active get doesn't meet the when clause..
case ! GetPrevalidate(aGet[ nGet ])
lSkiped = .t. // We skip the valid clause..
// Whats going on here ?
// We simulate a keystroke to bypass the actual get
// we do it directly, not with the keyboard command,
// for not running into any conflicts with pending keystrokes..
do case
* If we can't move upwards
case nGet <= 1
nKey = K_DOWN
* if we can't move downwards
case nGet >= len(aGet)
nKey = K_UP
* if last Key was Cursor up i.e., the current direction is Upwards
case nKey = K_UP
* just continue, nothing special to do...
* nKey = K_UP
otherwise
* default is moving downwards..
nKey = K_DOWN
endcase
case ( ValType( aGet[nGet]:reader ) == "B" )
Eval( aGet[nGet]:reader, aGet[nGet] ) // use custom reader block
nKey := lastkey()
otherwise
SETCURSOR( 1 ) // Cursor on...
nKey := INKEY( 0 ) // Change 0 in inkey(0) to another value
// to have gets with time out...
endcase
DO CASE
* Process hotkeys
case valtype(setkey(nkey)) == "B"
eval(setkey(nkey),"SCROLGET",0,aGet[nGet]:Name)
CASE nKey == K_ENTER .OR. nKey == K_TAB .or. nKey == K_DOWN
* we're moving down (Tab also moves down, just like in windows)
nGet++
CASE nKey == K_SH_TAB .or. nKey == K_UP
* we're moving up (Shift-Tab also moves up, just like in windows)
iif( nGet == 1, Nil, nGet-- )
CASE nKey == K_BS
aGet[ nGet ]:BACKSPACE()
CASE nKey == K_DEL
aGet[ nGet ]:DELETE()
CASE nKey == K_LEFT
aGet[ nGet ]:LEFT()
CASE nKey == K_RIGHT
aGet[ nGet ]:RIGHT()
CASE nKey == K_HOME
aGet[ nGet ]:HOME()
CASE nKey == K_END
aGet[ nGet ]:END()
CASE nKey == K_CTRL_LEFT
aGet[ nGet ]:WORDLEFT()
CASE nKey == K_CTRL_RIGHT
aGet[ nGet ]:WORDRIGHT()
CASE nKey == K_CTRL_HOME
nGet := 1
CASE nKey == K_CTRL_END
nGet := LEN( aGet )
CASE nKey == K_CTRL_T
aGet[ nGet ]:DELWORDRIGHT()
CASE nKey == K_CTRL_Y
aGet[ nGet ]:DELEND()
CASE nKey == K_CTRL_U
aGet[ nGet ]:UNDO()
// Toggles the INSERT mode
CASE nKey == K_INS
lInsert := iif( lInsert, .F., .T. )
// Place your own Statments here to show new Status
/*
@12, 64 SAY iif( lInsert, ' INS ', ' OVR ' )
*/
* it's a character to be entered...
CASE Range( nKey, 32, 160 ) // Non americans still exist out there...
iif( lInsert, aGet[ nGet ]:INSERT( CHR( nKey ) ),;
aGet[ nGet ]:OVERSTRIKE( CHR( nKey ) ) )
case nKey = K_PGUP .or. nKey = K_PGDN .or.;
nKey = K_CTRL_PGUP .or. nKey = K_CTRL_PGDN
// dummy - will be processed below
* user wants out...
CASE nKey == K_F10 .OR. nKey == K_ESC
// Pop up an Exit dialog box
nKey := iif( TimeToExit() = 1, K_F10, 0 )
ENDCASE
* we're beyond the last get, so ask the user if sHe wants to exit..
IF nGet == LEN( aGet ) + 1
// Pop up an Exit dialog box
iif( TimeToExit() == 1, nKey := K_F10, NIL )
nGet := LEN( aGet )
ENDIF
// If the GET has changed, the old GET loses it's focus
IF nLastGet != nGet .or.;
nKey = K_PGUP .or. nKey = K_PGDN .or.;
nKey = K_CTRL_PGUP .or. nKey = K_CTRL_PGDN
* First Look, if the get meets the Validclause
if ! lSkiped .and. ! GetPostValidate(aGet[nLastget])
* if it doesn't don't leave the get, reforce new input..
nGet = nLastget
loop
endif
// Kill the focus of the last get and set it to unselected Color
GetFocus( aGet[ nLastGet ], .F.)
/*****************************************
0 1════════╗
1 2 ║
2 1──3────────╫────┐ Boxtop =2
3 2 4BGTOP=4 ║ │
4 3 5 ║ │ Boxh =5
5 4 6BGbot=6 ║ │
6 5──7────────╫────┘ Boxbot =6
7 8════════╝ BGh =8
******************************************/
do case
* new getrow is outside the window - time to scroll gets..
case aGet[nGet]:Row <= Boxtop .or. aGet[nGet]:Row >= Boxtop+Boxh-1
ScrollNext(aGet,nGet,nLastget, Boxtop,Boxh,@BGtop,bgh)
* Show the new Background...
ShowGetBG(GetBG,Boxtop,Boxleft,Boxw,BGTOP,Boxh-2,BGcolor)
* Show the new Gets, set focus to new get
ShowGets(aGet,nGet,Boxtop,Boxh)
case nKey = K_PGUP .or. nKey = K_PGDN .or.;
nKey = K_CTRL_PGUP .or. nKey = K_CTRL_PGDN
do case
case nKey == K_PGUP
BGTop := max(BGtop-Boxh+2,1)
case nKey == K_PGDN
BGTop := min(BGtop+Boxh-2,BGh-Boxh+3)
case nKey == K_CTRL_PGUP
BGTop = 1
case nKey == K_CTRL_PGDN
BGTop = BGh-Boxh+3
endcase
nGet := FirstGetinBox(aGet,BGTop,Boxh)
NewGetRows(aGet,Boxtop,Bgtop)
* Show the new Background...
ShowGetBG(GetBG,Boxtop,Boxleft,Boxw,BGTOP,Boxh-2,BGcolor)
* Show the new Gets, set focus to new get
ShowGets(aGet,nGet,Boxtop,Boxh)
otherwise
* set focus to new get
GetFocus( aGet[ nGet ], .T.)
endcase
* Save values
nLastGet := nGet
ENDIF
// Returns the cursor in the current GET
DEVPOS( aGet[ nGet ]:ROW, aGet[ nGet ]:COL + aGet[ nGet ]:POS - 1 )
ENDDO
// make sure getfield isn't active any more
// this is especialy important for "V"iew mode
GetFocus( aGet[ nGet ], .f.)
// Restore the getlist's original Boxrows
// coment this out, if you want to process the actual Row and Column settings
// within the calling routine..
aeval(aGet,{|oGet|oGet:Row := oGet:cargo[CARGO_ROW], oGet:Col := oGet:cargo[CARGO_COL]})
setkey(K_F10,bO_f10key) // restore orignal F10-Key settings
setcursor(nO_cursor) // restore the cursor
setcolor(cO_color) // restore the color
RETURN nKey != K_ESC // Will return .t. if User wants to save changes,
// otherwise will return .f. (User Escaped)
// The Bottom of the Box is calculated as Boxtop plus
// Boxheigth -1 (see Grafic above)
// extra step to make the code more readable
// converted to Preprocessor constant for better runtime performance
#define Boxbot (Boxtop+Boxh-1)
*-----------------------------------------------------------------
function FirstGetinBox(aGet,BGTop,Boxh)
local nKounter, nMin, oGet
nMin := MaxGetRow(aGet)
for nKounter :=1 to len(aGet)
oGet:=aGet[nKounter]
if oGet:cargo[CARGO_ROW] >= BGTop .and. oGet:cargo[CARGO_ROW]<=Bgtop+Boxh-2
if oGet:cargo[CARGO_ROW] < aGet[nMin]:cargo[CARGO_ROW] .or.;
(oGet:cargo[CARGO_ROW] = aGet[nMin]:cargo[CARGO_ROW] .and.;
oGet:cargo[CARGO_COL] < aGet[nMin]:cargo[CARGO_COL] )
nMin :=nKounter
endif
endif
next
/*
nKounter :=0
aeval(aGet,{|Get|nKounter++,nMin :=;
iif(Get:cargo[CARGO_ROW] >= BGTop .and. Get:cargo[CARGO_ROW]<=Bgtop+Boxh-2,;
iif(Get:cargo[CARGO_ROW] < aGet[nMin]:cargo[CARGO_ROW] .or.;
(Get:cargo[CARGO_ROW] = aGet[nMin]:cargo[CARGO_ROW] .and.;
Get:cargo[CARGO_COL] < aGet[nMin]:cargo[CARGO_COL] ),;
nKounter, nMin),nMin)})
1 CP P
aeval(aGet,{|Get|nKounter++,nMin :=;
2 I1
iif(Get:cargo[CARGO_ROW] >= BGTop .and. Get:cargo[CARGO_ROW]<=Bgtop+Boxh-2,;
3
iif(Get:cargo[CARGO_ROW] < aGet[nMin]:cargo[CARGO_ROW] .or.;
4
(Get:cargo[CARGO_ROW] = aGet[nMin]:cargo[CARGO_ROW] .and.;
4 I2
Get:cargo[CARGO_COL] < aGet[nMin]:cargo[CARGO_COL] ) ,;
E2 3 E1 2C1
nKounter, nMin) ,nMin)})
*/
return nMin
*-----------------------------------------------------------------
function MaxGetrow(aGet)
local nMax := 0
local nKounter
if nMax < 1
nMax := 1
nKounter :=0
for nKounter := 1 to len(aGet)
if aGet[nKounter]:cargo[CARGO_ROW]>aGet[nMax]:cargo[CARGO_ROW]
nMax := nKounter
endif
next
/*
nMax := aeval(aGet,{|oGet|nKounter++, ;
nMax := iif(oGet:cargo[CARGO_ROW]>aGet[nMax]:cargo[CARGO_ROW], nKounter, nMax)})
*/
endif
return nMax
*-----------------------------------------------------------------
static function ScrollNext(aGet,nGet,nLastget, Boxtop,Boxh,BGtop,Bgh)
/*****************************************
0 11 ║
1 12 * ║ *:row = 1, *:cargo[CARGO_ROW]=12
2 1─13─────────╫────┐ Boxtop =2
3 2 14BGTOP=14 ║ │
4 3 15 ║ │ Boxh =5
5 4 16BGbot=16 ║ │
6 5─17─────────╫────┘ Boxbot =6
7 18══#══════╝ BGh =18 #:row = 7, #:cargo[CARGO_ROW] = 18
******************************************/
BGTop := BGtop-(aGet[nLastget]:cargo[CARGO_ROW]-aGet[nGet]:cargo[CARGO_ROW])
BGTop := max(min(BGtop,BGh-Boxh+3),1)
NewGetRows(aGet,Boxtop,Bgtop)
return nil
*-----------------------------------------------------------------
function ShowGetBG(GetBG,Boxtop,Boxleft,Boxw,BGTOP,nLines,cColor)
local cO_Color := setcolor(), nRow := Boxtop
* the 6th Parameter is optional, default is the actual color
if pcount() > 6
cO_color := setcolor(cColor)
endif
* GetBg is an array, where every element represents one line of the Background
* now display those lines, wich fit into the frame
* (see 3rd and 4th Parameter to aeval)
* Doing this with aeval is much faster than a for next loop..
aeval(GetBG,{|Line|devpos(++nRow,Boxleft+1),devout(padr(line,Boxw-2))},BGTop,nLines)
setcolor(cO_color) // Reset the color setting
return nil
*-----------------------------------------------------------------
// Next two functions interface between real screen coordinates and the
// virtual ones..
static function NewGetRows(aGet,Boxtop,Bgtop)
// Internaly (in cargo[CARGO_ROW]), we have virtual Rows for every Get.
// Numbering starts with 1, So that the First virtual Row is Number 1,
// the second 2 etc.
// This function is to update the "real" (i.e. Get:Row) Rows of the
// getfield..
// The real job, to find out how many lines to shift, has been done above
// within the UDF ScrollNext()
//
// If you're using scrolling gets with funcky's window functions
// place a call to NewGetCols and NewGetRows every time the window has
// been moved
local Shift := Boxtop-Bgtop+1
aeval(aGet,{|oGet|oGet:Row := oGet:cargo[CARGO_ROW] + Shift})
/*
* Above eval() should be equivalent to :
for nKounter := 1 to len(aGet)
aGet[nKounter]:Row := aGet[nKounter]:cargo[CARGO_ROW] + Shift
next
*/
return nil
*-----------------------------------------------------------------
static function NewGetCols(aGet,Boxleft)
// Internaly (in cargo[CARGO_COL]), we have virtual Columns for every Get.
// Numbering starts with 0, So that the First virtual Column is Number 0,
// the second 1 etc.
// This function is to update the "real" (i.e. Get:Col) Columns of the
// getfield..
// We just add the left column of the Box (+1 for the frame)
// to every Getcolumn.
// As we don't expect the Box to shift and we don't implemented
// horizontal scrolling, this has to be done only once (at startup time)
//
// If you're using scrolling gets with funcky's window functions
// place a call to NewGetCols and NewGetRows every time the window has
// been moved
local Shift := Boxleft+1
* 1 CP P S IS S C1
aeval(aGet,{|oGet| oGet:Col := oGet:cargo[CARGO_COL] + Shift})
return nil
*-----------------------------------------------------------------
static function ShowGets(aGet,nGet,Boxtop,Boxh)
local nKounter:=0
AEVAL(aGet, {|oGet|nKounter++,;
iif(oGet:Row>Boxtop .and. oGet:Row<Boxbot,;
iif(nKounter == nGet,;
GetFocus( oGet,.t.),;
oGet:display()),;
NIL)})
/*
* I personaly use this numbering System, to check for bracket-related typos
* within complex expressions (when I start getting confused) :
1 CP P
AEVAL(aGet, {|oGet,nKounter|nKounter++,;
2 S I1
iif(oGet:Row>Boxtop .and. oGet:Row<Boxbot,;
3 I2
iif(nKounter == nGet,;
4 4 T2
GetFocus( oGet,.t.) ,;
44 3 T1
oGet:display() ) ,;
2 C 1
NIL) } )
*/
/*
** The Aeval above should do the same job as the following Statements
** (only much faster)
** (I usualy write the Clipper S'87 code first before translating
** it to Clipper5's aeval()-Expressions)
for nKounter := 1 to len(aGet)
// if the getfiled is within the frame
if aGet[nKounter]:Row > GetTRow .and. aGet[nKounter]:Row < GetBRow
// if it's the cative getfield
if nKounter == nGet
// Tell the getsystem
GetFocus(aGet[nKounter],.t.)
else
// otherwise display "only"
aGet[nKounter]:display()
endif
else
// If we know that the GetList is ordered by Rows
// Rather the by colums or otherwise...
// We could place an "Exit"-Statement at this place..
endif
next
*/
return nil
*-----------------------------------------------------------------
* Function GetFocus()
*
// If lFocus is true the GET receives input focus
// If lFocus is false the GET's input focus is taken away.
static FUNCTION GetFocus( oGetObj, lFocus)
IF lFocus
oGetObj:SETFOCUS()
// Returns the cursor to the current Get
// DEVPOS( oGetObj:ROW, oGetObj:COL )
ELSE
oGetObj:KILLFOCUS()
ENDIF
RETURN nil
*-----------------------------------------------------------------
// The next two functions are the Functions from Nantucket's Getsys.prg
// to check When and Valid - Clauses...
/***
* GetPreValidate()
*/
static function GetPreValidate(get)
local when := .t.
if ( get:preBlock <> NIL )
when := Eval(get:preBlock, get)
get:Display()
end
return (when)
static function GetPostValidate(get)
local saveUpdated
local changed, valid := .t.
if ( get:BadDate() )
get:Home()
return (.f.)
end
if ( get:changed )
get:Assign()
end
get:Reset()
if ( get:postBlock <> NIL )
// S87 compat.
SetPos( get:row, get:col + Len(get:buffer) )
valid := Eval(get:postBlock, get)
// reset compat. pos
SetPos( get:row, get:col )
get:UpdateBuffer()
end
return (valid)
*-----------------------------------------------------------------
function Shad( nTR, nTC, nBR, nBC, lDoub, cClrs )
// Shad() used to be in Nantucket Canada's funs.ch file.
// I transfered it to a function for easy use in codeblocks
local cDefCol:=SETCOLOR( IF( EMPTY( cClrs ), Nil, cClrs ) )
SETCOLOR( 'w+/n' )
dispBOX( nTR+1, nTC+2, nBR+1, nBC+2, '░░░░░░░░░' )
SETCOLOR( cClrs )
scroll( nTR, nTC, nBR, nBC,0)
IF lDoub
dispbox( nTR, nTC, nBR, nBC, 2 )
endif
SETCOLOR( cDefCol )
return nil
*-----------------------------------------------------------------
// This last function pops up when the user is assumed to leave the gets
// You can throw it out or replace it with your own function.
// Non-english programs should at least translate the messages...
//
// it's also more or less from Nantucket Canada, especialy the nice
// Boxing/Shadowing functions used therein..
* * * *
*
* Function TimeToExit()
*
// Exit Dialog Box
static FUNCTION TimeToExit()
LOCAL cDefcol // needed and initialized within BoxShad() (See Funcs.ch)
local cDefColor := SETCOLOR( 'w+/r' )
local cScrn := SAVESCREEN( 8, 30, 13, 54 )
LOCAL nExitCh := 1
BoxShad( 8, 30, 12, 52, 'w+/r' )
if lastkey() == K_ESC
@9, 36 SAY 'Abort without'
@10,33 SAY 'Saving changes ?'
else
@9, 36 SAY 'End Editing'
@10,33 say 'and save changes ?'
endif
@11, 36 PROMPT ' YES '
@11, 42 PROMPT ' NO '
MENU TO nExitCh
SETCOLOR( cDefColor )
RESTSCREEN( 8, 30, 13, 54, cScrn )
RETURN nExitCh
******
* EOF
******